package com.example.demo.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.example.demo.ao.CensusDataAo;
import com.example.demo.service.ThreadConcurrencyService;
import com.example.demo.vo.CensusDataVo;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
//http://localhost:8080/image/download/speed?pageNo=1
@RestController
@RequestMapping("/image/download")
@Slf4j
public class ImageDownLoadController {

    @Autowired
    private ThreadConcurrencyService threadConcurrencyService;

    // 每次导出的数据量
    private static final int EXPORT_BATCH_SIZE = 2000;
    // 每个线程处理的数据量
    private static final int THREAD_BATCH_SIZE = 200;
    // 核心线程数
    private static final int CORE_THREAD_POOL_SIZE = 8;

    // 创建固定大小的线程池
    private static final ExecutorService FIXED_THREAD_POOL =
            Executors.newFixedThreadPool(CORE_THREAD_POOL_SIZE);

    @GetMapping("/speed")
    public void censusDataSpeed(HttpServletResponse response, CensusDataAo censusDataAo)
            throws IOException, InterruptedException {

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("普查明细", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        int pageNo = censusDataAo.getPageNo();

        // 确保每次最多导出2000条
        int actualPageSize = EXPORT_BATCH_SIZE;

        // 计算线程数
        int threadCount = (actualPageSize + THREAD_BATCH_SIZE - 1) / THREAD_BATCH_SIZE;
        threadCount = Math.min(threadCount, CORE_THREAD_POOL_SIZE);


        log.info("开始导出第{}页数据, 总大小: {}, 使用线程数: {}",
                pageNo, actualPageSize, threadCount);

        // 存储结果
        List<CensusDataVo>[] results = new List[threadCount];
        CountDownLatch latch = new CountDownLatch(threadCount);
        AtomicInteger errorCount = new AtomicInteger(0);

        // 计算基础偏移量
        int baseOffset = (pageNo - 1) * actualPageSize;

        // 提交线程任务
        for (int i = 0; i < threadCount; i++) {
            final int threadIndex = i;
            int start = i * THREAD_BATCH_SIZE;
            int end = Math.min((i + 1) * THREAD_BATCH_SIZE, actualPageSize);
//            int threadPageSize = end - start;
            int threadPageSize = Math.min(THREAD_BATCH_SIZE, actualPageSize - start);

            if (threadPageSize <= 0) break;

            FIXED_THREAD_POOL.execute(() -> {
                try {
                    // 创建线程特定的查询参数
                    CensusDataAo threadAo = new CensusDataAo();
                    BeanUtils.copyProperties(censusDataAo, threadAo);

                    // 计算线程内的偏移量
                    int threadOffset = baseOffset + start;
                    threadAo.setOffset(threadOffset);
                    threadAo.setLimit(threadPageSize);

                    // 执行查询
                    results[threadIndex] = threadConcurrencyService.censusDataSpeed(threadAo);

                    log.debug("线程{}完成查询: {}条数据", threadIndex,
                            results[threadIndex] != null ? results[threadIndex].size() : 0);
                } catch (Exception e) {
                    log.error("线程{}查询失败: {}", threadIndex, e.getMessage());
                    errorCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }

        // 等待所有线程完成
        latch.await();

        // 检查错误
        if (errorCount.get() > 0) {
            throw new RuntimeException("部分线程查询失败，共" + errorCount.get() + "个错误");
        }

        // 合并结果
        List<CensusDataVo> mergedData = new ArrayList<>(actualPageSize);
        for (List<CensusDataVo> list : results) {
            if (list != null) {
                mergedData.addAll(list);
            }
        }

        log.info("第{}页数据查询完成，实际获取{}条数据", pageNo, mergedData.size());

        // 配置Excel样式
        WriteCellStyle headStyle = new WriteCellStyle();
        headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        WriteCellStyle contentStyle = new WriteCellStyle();
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(headStyle, contentStyle);

        // 写入Excel
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), CensusDataVo.class)
                .registerWriteHandler(styleStrategy)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .build()) {

            WriteSheet sheet = EasyExcel.writerSheet("普查信息")
                    .build();
            excelWriter.write(mergedData, sheet);
        }
    }
}
